package com.explorx.sns.puma.im.core.chat.impl;

import com.explorex.puma.common.utils.SnowflakeIdWorker;
import com.explorx.sns.puma.im.core.chat.PrivateMessageService;
import com.explorx.sns.puma.im.core.chat.consts.MessageStatusEnum;
import com.explorx.sns.puma.im.core.chat.model.PrivateMessageModel;
import com.explorx.sns.puma.im.core.chat.ConversationService;
import com.explorx.sns.puma.im.core.chat.MessageService;
import com.explorx.sns.puma.im.core.chat.consts.StatusEnum;
import com.explorx.sns.puma.im.core.chat.model.MessageModel;
import com.explorx.sns.puma.im.core.dal.dao.MessageEntityMapper;
import com.explorx.sns.puma.im.core.dal.entity.MessageEntity;
import com.explorx.sns.puma.im.core.dal.entity.MessageEntityExample;
import com.google.common.collect.Lists;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MessageServiceImpl implements MessageService {

    @Resource
    private MessageEntityMapper messageEntityMapper;

    @Resource
    private ConversationService conversationService;

    @Resource
    private PrivateMessageService privateMessageService;

    @Override
    public List<MessageModel> batchGetMessageByIds(List<Long> msgIds) {
        MessageEntityExample example=new MessageEntityExample();
        example.createCriteria().andMessageIdIn(msgIds);
        final List<MessageEntity> messageEntities = messageEntityMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(messageEntities)) {
            List<MessageModel> result= Lists.newArrayList();
            for (MessageEntity messageEntity : messageEntities) {
                result.add(transfer(messageEntity));
            }
            return result;
        }
        return Collections.EMPTY_LIST;
    }

    private MessageModel transfer(MessageEntity messageEntity){
        return MessageModel.builder()
                .messageId(messageEntity.getMessageId())
                .uuid(messageEntity.getUuid())
                .messageType(messageEntity.getMessageType())
                .messageContent(messageEntity.getContent())
                .createTime(messageEntity.getCreateTime().getTime())
                .updateTime(messageEntity.getUpdateTime().getTime())
                .cid(messageEntity.getCid())
                .senderId(messageEntity.getSenderId())
                .status(messageEntity.getStatus()).build();
    }

    @Override
    public List<MessageModel> getConversationMessage(Long uid, Long cid) {
        MessageEntityExample example=new MessageEntityExample();
        example.createCriteria().andStatusNotEqualTo(MessageStatusEnum.Revoke.getStatus())
                .andCidEqualTo(cid);
        final List<MessageEntity> messageEntities = messageEntityMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(messageEntities)) {
            final List<Long> privateMsgIds = messageEntities.stream()
                    .filter(ele -> ele.getStatus() == MessageStatusEnum.Part_Seen.getStatus())
                    .map(MessageEntity::getMessageId)
                    .collect(Collectors.toList());

            final List<PrivateMessageModel> privateMessageModels = privateMessageService.queryPrivateMessageByIds(uid, cid, privateMsgIds);
            final Map<Long, PrivateMessageModel> privateMessageModelMap = privateMessageModels.stream().collect(Collectors.toMap(PrivateMessageModel::getMessageId, ele -> ele));
            List<MessageModel> result= Lists.newArrayList();
            for (MessageEntity messageEntity : messageEntities) {
                final PrivateMessageModel privateMessageModel = privateMessageModelMap.get(messageEntity.getMessageId());
                if(privateMessageModel!=null){
                    if (privateMessageModel.getStatus()== MessageStatusEnum.OK.getStatus()) {
                        result.add(transfer(messageEntity));
                    }
                }else {
                    result.add(transfer(messageEntity));
                }
            }
            return result;
        }
        return Collections.EMPTY_LIST;
    }

    @Override
    public MessageModel queryConvMessage(Long cid, Long msgId) {
        MessageEntityExample example=new MessageEntityExample();
        example.createCriteria().andCidEqualTo(cid).andMessageIdEqualTo(msgId);
        final List<MessageEntity> messageEntities = messageEntityMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(messageEntities)){
            return null;
        }
        return transfer(messageEntities.get(0));
    }

    @Override
    public Long saveMessage(MessageModel messageModel) {
        MessageEntity entity=new MessageEntity();
        entity.setCid(messageModel.getCid());
        entity.setContent(messageModel.getMessageContent());
        entity.setMessageType((byte) messageModel.getMessageType());
        long msgId= SnowflakeIdWorker.nextId();
        messageModel.setMessageId(msgId);
        entity.setMessageId(msgId);
        entity.setUuid(messageModel.getUuid());
        entity.setSenderId(messageModel.getSenderId());
        entity.setStatus((byte) StatusEnum.OK.getValue());
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        final int insert = messageEntityMapper.insert(entity);
        // 更新会话最近一条消息
        final boolean b = conversationService.updateLastMsg(messageModel);
        if ( b && insert>0) {
            return  msgId;
        }
        return  0L;
    }

    @Override
    public boolean revokeMessage(Long cid, Long msgId) {
        return  updateMessageStatus(cid,msgId, MessageStatusEnum.Revoke.getStatus())>0;
    }

    private int updateMessageStatus(Long cid, Long msgId,int status){
        MessageEntity entity=new MessageEntity();
        entity.setStatus((byte) status);
        MessageEntityExample example=new MessageEntityExample();
        example.createCriteria().andCidEqualTo(cid).andMessageIdEqualTo(msgId);
        return messageEntityMapper.updateByExampleSelective(entity,example);
    }

    @Override
    public boolean deleteMessage(Long senderId, Long cid, Long msgId) {
        final int updatedMsg = updateMessageStatus(cid, msgId, MessageStatusEnum.Part_Seen.getStatus());
        if(updatedMsg<=0){
            return  false;
        }
        PrivateMessageModel privateMessageModel=PrivateMessageModel.builder()
                .cid(cid)
                .senderId(senderId)
                .status(MessageStatusEnum.Delete.getStatus())
                .messageId(msgId).build();
        return privateMessageService.deleteMessage(privateMessageModel);
    }
}
